<template>
  <div>
    <!-- 19 增加全屏按钮 -->
    <!-- 20 用控制面板控制全屏
       <button class="full-screen-btn" @click="onClickFullScreen">全屏</button> 
      -->
  </div>
</template>

<script>
import * as THREE from "three";
// 导入轨道控制器
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls.js";
// 20 导入gui控制面板
import { GUI } from "three/examples/jsm/libs/lil-gui.module.min.js";

// 导入HDR加载器
import { RGBELoader } from "three/examples/jsm/loaders/RGBELoader";

// 31.1 导入gltf加载器
import { GLTFLoader } from "three/examples/jsm/loaders/GLTFLoader";

// 32.1 导入DracoLoader
import { DRACOLoader } from "three/examples/jsm/loaders/DRACOLoader";

/**
 * 值类型
 * - Vector3
 * (x,y,z)
 * - Euler 欧拉: 描述一个旋转变换,通过指定轴顺序和其各个轴向上的指定旋转角度来旋转一个物体
 * (x,y,z,order) - order: 'XYZ' or 'YXZ' or 'ZXY' or 'ZYX',
 */

export default {
  data() {
    return {};
  },
  methods: {
    // 19 增加全屏按钮
    onClickFullScreen() {
      // 渲染器画布全屏
      window.renderer && window.renderer.domElement.requestFullscreen();
      // 浏览器窗口全屏
      // document.body.requestFullscreen()
      // 退出全屏
      // document.exitFullscreen()
    },
  },
  mounted() {
    // 1 创建场景
    const scene = new THREE.Scene();

    // 2 创建相机
    const camera = new THREE.PerspectiveCamera(
      75,
      window.innerWidth / window.innerHeight,
      0.1,
      1000,
    );
    camera.position.z = 5;
    camera.position.x = 5;
    camera.position.y = 5;
    // 3 相机指向原点
    camera.lookAt(new THREE.Vector3(0, 0, 0));

    // 4 创建一个渲染器 canvas
    const renderer = new THREE.WebGLRenderer({
      // 4.1.1 设置渲染器锯齿属性
      antialias: true,
    });
    // 4.1.2 属性设置
    // renderer.antialias = true
    renderer.setSize(window.innerWidth, window.innerHeight);

    document.body.appendChild(renderer.domElement);

    // 8 添加轨道控制器
    const controls = new OrbitControls(camera, renderer.domElement); // 创建轨道控制器, 第二参数表示监听事件的DOM
    // const controls = new OrbitControls(camera, document.body); // 创建轨道控制器, 第二参数表示监听事件的DOM, 监听了body后, OrbitControls会拦截所有的事件
    // 9 设置阻尼
    controls.enableDamping = true;
    controls.dampingFactor = 0.1; // 设置阻尼系数, 数值越小, 惯性越大, 数值越大, 停下来越快

    // 10 自动旋转
    controls.autoRotate = false; // 自动旋转

    // 7 添加世界坐标辅助器 x轴向右红色r y轴向上绿色g z轴向前蓝b
    const axesHelper = new THREE.AxesHelper(5); // 辅助线长度为5
    scene.add(axesHelper);

    // 6 动作绘制
    function animate() {
      /* 8 添加轨道控制器 根据控制器更新画面 */
      controls.update();
      requestAnimationFrame(animate); // 请求浏览器重新绘制画面
      /* 自动旋转
      cube.rotation.x += 0.01; // x轴旋转速度增加
      cube.rotation.y += 0.01; // y轴旋转速度增加
      */
      renderer.render(scene, camera); // 渲染场景和相机设置到屏幕上
    }
    animate(); // 开始动画循环

    // 18 监听全屏事件, 让画布适配屏幕尺寸
    window.addEventListener("resize", function() {
      // 重置渲染器宽高比
      renderer.setSize(window.innerWidth, window.innerHeight);
      // 4.2 设置设备像素比
      renderer.setPixelRatio(window.devicePixelRatio);
      // 重置相机宽高比
      camera.aspect = window.innerWidth / window.innerHeight;
      // 更新相机投影矩阵
      camera.updateProjectionMatrix();
    });
    /** 20 用GUI控制面板控制全屏
    // 19 增加全屏按钮
    window.scene = scene;
    window.camera = camera;
    window.renderer = renderer;
    window.controls = controls;
    */
    // 20 GUI控制面板
    let eventObj = {
      Fullscreen: function() {
        document.body.requestFullscreen();
      },
      ExitFullscreen: function() {
        document.exitFullscreen();
      },
    };
    const gui = new GUI();
    // 第一个参数是事件对象, 第二个参数是该事件对象的key
    gui.add(eventObj, "Fullscreen").name("全屏");
    gui.add(eventObj, "ExitFullscreen").name("退出全屏");
    
    const ballMeshes = []

    // 创建三个球体
    function createdBall({ position, color }) {
      const ballMesh1 = new THREE.Mesh(
        new THREE.SphereBufferGeometry(1, 16, 16),
        new THREE.MeshBasicMaterial({
          color: color,
        }),
      );
      ballMesh1.position.x = position;
      ballMesh1._originColor = color
      ballMeshes.push(ballMesh1)
      scene.add(ballMesh1);
    }

    createdBall({
      position: -5,
      color: 0x00ff00,
    });
    createdBall({
      position: 0,
      color: 0x0000ff,
    });
    createdBall({
      position: 5,
      color: 0x00ffff,
    });

    // 21 利用Ray射线实现canvas交互
    // 21.1 创建射线
    const raycaster = new THREE.Raycaster();

    // 21.2 创建鼠标向量保存点击位置数据
    const mouse = new THREE.Vector2();

    // 21.3 监听画布点击事件, 获取点击的坐标
    renderer.domElement.addEventListener("click", (e) => {
      ballMeshes.forEach(mesh => {
        mesh.material.color.set(mesh._originColor)
      })
      // mouse的取值范围 [-1, 1], 根据屏幕点击的位置计算mouse的取值区间
      mouse.x = (e.clientX / window.innerWidth) * 2 - 1;
      mouse.y = -((e.clientY / window.innerHeight) * 2 - 1);
      // 通过摄像机和鼠标位置更新射线
      raycaster.setFromCamera(mouse, camera);

      // 获取物体和射线的焦点碰撞结果
      const intersects = raycaster.intersectObjects(ballMeshes); // 入参为数组, 射线于入参的碰撞测试
      if(intersects.length > 0) {
        intersects[0].object.material.color.set(0xffff00)
      }
    });
  },
};
</script>

<style>
* {
  margin: 0;
  padding: 0;
}
body {
  height: 100vh;
  width: 100vw;
  overflow: hidden;
}

.full-screen-btn {
  position: fixed;
  left: 2vw;
  top: 2vh;
  z-index: 2;
}
</style>
